﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using System.Web;
using Dropit.BlogPageProvider.Blog;

namespace Dropit.BlogPageProvider
{
	public class PageStore : EPiServer.Research.PageProviders.MappedPageProvider
	{
		#region Fields

		private static string BlogPrefix = "Blog_";
		private static string PostPrefix = "Post_";
		private static string CommentPrefix = "Comment_";

		#endregion

		protected override List<string> GetChildren(string key)
		{
			KeyType type = GetKeyType(key);
			if (type == KeyType.Blog)
			{
				IBlog blog = BlogService.Instance.GetBlogById(CurrentConnection, ExtractKey(key));
				if (blog != null)
				{
					return BlogService.Instance.GetPosts(CurrentConnection, ExtractKey(key)).Select<IPost, string>(post => string.Concat(PageStore.PostPrefix, post.Id)).ToList();
				}
			}
			else if (type == KeyType.Post)
			{
				IPost post = BlogService.Instance.GetPostById(CurrentConnection, ExtractKey(key));
				if (post != null)
				{
					return BlogService.Instance.GetComments(CurrentConnection, ExtractKey(key)).Select<IComment, string>(comment => string.Concat(PageStore.CommentPrefix, comment.Id)).ToList();
				}
			}
			return new List<string>(0);
		}

		protected override PageData GetPage(string key)
		{
			KeyType type = GetKeyType(key);
			if (type == KeyType.Blog)
			{
				IBlog blog = BlogService.Instance.GetBlogById(CurrentConnection, ExtractKey(key));
				if (blog != null)
				{
					PageData pd = new PageData();
					InitializePageData(pd, key, blog.Name.HtmlDecode(), null);
					pd["Summery"] = blog.Summery.HtmlDecode();
					pd["PageStartPublish"] = blog.Created;
					pd["PageChanged"] = blog.Created;
					pd["PageCreated"] = blog.Created;
					return pd;
				}
			}
			else if (type == KeyType.Post)
			{
				IBlog blog = BlogService.Instance.GetBlogById(CurrentConnection, ExtractKey(key));
				IPost post = BlogService.Instance.GetPostById(CurrentConnection, ExtractKey(key));
				if (post != null && blog!=null)
				{
					PageData pd = new PageData();
					InitializePageData(pd, key, post.Heading.HtmlDecode(), string.Concat(PageStore.BlogPrefix, blog.Id));
					pd["Content"] = post.Content.HtmlDecode();
					pd["PageStartPublish"] = post.Created;
					pd["PageChanged"] = post.Created;
					pd["PageCreated"] = post.Created;
					if (post.Category.Count > 0)
					{
						StringBuilder categories = new StringBuilder();
						foreach (string category in post.Category)
						{
							categories.AppendFormat("{0}, ", category);
						}
						pd["Category"] = categories.ToString().Trim().TrimEnd(',');
					}
					return pd;
				}
			}
			else if (type == KeyType.Comment)
			{
				IPost post = BlogService.Instance.GetPostById(CurrentConnection, ExtractKey(key));
				IComment comment = BlogService.Instance.GetCommentById(CurrentConnection, ExtractKey(key));
				if (comment != null && post != null)
				{
					PageData pd = new PageData();
					InitializePageData(pd, key, comment.Heading.Shorten(15).HtmlDecode(), string.Concat(PageStore.PostPrefix, post.Id));
					pd["Content"] = comment.Content.HtmlDecode();
					pd["PageStartPublish"] = comment.Created;
					pd["PageChanged"] = comment.Created;
					pd["PageCreated"] = comment.Created;
					return pd;
				}
			}
			return null;
		}

		protected override int GetPageTypeId(string key)
		{
			switch (GetKeyType(key))
			{
				case KeyType.Blog:
					return Settings.BlogPageTypeId;
				case KeyType.Post:
					return Settings.PostPageTypeId;
				case KeyType.Comment:
					return Settings.CommentPageTypeId;
			}
			return -1;
		}

		protected override List<string> GetRootChildren()
		{
			PageData pageData = EPiServer.DataFactory.Instance.GetPage(EntryPoint);
			if (pageData != null)
			{
				//if (pageData.PageTypeID == BloggPostPageStore.BlogPageTypeId)
				{
					return BlogService.Instance.GetBlogs(CurrentConnection).Select<IBlog, string>(blog => string.Concat(PageStore.BlogPrefix, blog.Id)).ToList();
				}
			}
			return new List<string>(0);
		}

		public override void Delete(string key, bool forceDelete)
		{
			switch (GetKeyType(key))
			{
				case KeyType.Post:
					BlogService.Instance.DeletePost(CurrentConnection, ExtractKey(key));
					break;
				case KeyType.Comment:
					BlogService.Instance.DeleteComment(CurrentConnection, ExtractKey(key));
					break;
			}
		}

		/// <summary>
		/// We can't move a blog post so just delete the post insted.
		/// </summary>
		/// <param name="pageLink"></param>
		public override void MoveToWastebasket(PageReference pageLink)
		{
			Delete(pageLink, true);
		}

		public override void Save(PageData page, string key, EPiServer.DataAccess.SaveAction action)
		{
			string id = ExtractKey(key);
			switch (GetKeyType(key))
			{
				case KeyType.Post:
					IPost post = BlogService.Instance.GetPostById(CurrentConnection,ExtractKey(key));
					post.Heading = page.PageName;
					post.Content = page.Property["Content"].ToString();
					post.Category = new List<string>(page.Property["Category"].ToString().Split(','));
					BlogService.Instance.UpdatePost(CurrentConnection, post);
					break;
				case KeyType.Comment:
					IComment comment = BlogService.Instance.GetCommentById(CurrentConnection, ExtractKey(key));
					comment.Heading = page.PageName;
					comment.Content = page.Property["Content"].ToString();
					BlogService.Instance.UpdateComment(CurrentConnection, comment);
					break;
			}
		}

		public override string SaveNew(PageData page, string parentKey, EPiServer.DataAccess.SaveAction action)
		{
			string id = ExtractKey(parentKey);
			switch (GetKeyType(parentKey))
			{
				case KeyType.Blog:
					IPost post = BlogService.Instance.CreatePost(CurrentConnection);
					post.Heading = page.PageName;
					post.Content = page.Property["Content"].ToString();
					post.Created = DateTime.Now;
					post.Category = new List<string>(page.Property["Category"].ToString().Split(','));
					id = BlogService.Instance.SavePost(CurrentConnection, id, post);
					if (!string.IsNullOrEmpty(id))
					{
						return string.Concat(PageStore.PostPrefix, id);
					}
					break;
				case KeyType.Post:
					IComment comment = BlogService.Instance.CreateComment(CurrentConnection);
					comment.Heading = page.PageName;
					comment.Content = page.Property["Content"].ToString();
					comment.Created = DateTime.Now;
					id = BlogService.Instance.SaveComment(CurrentConnection, id, comment);
					if (!string.IsNullOrEmpty(id))
					{
						return string.Concat(PageStore.CommentPrefix, id);
					}
					break;
			}
			return string.Empty;
		}

		#region Helper Methods

		private KeyType GetKeyType(string key)
		{
			if (key.StartsWith(PageStore.BlogPrefix))
			{
				return KeyType.Blog;
			}
			else if (key.StartsWith(PageStore.PostPrefix))
			{
				return KeyType.Post;
			}
			else if (key.StartsWith(PageStore.CommentPrefix))
			{
				return KeyType.Comment;
			}
			return KeyType.Unknown;
		}

		private string ExtractKey(string key)
		{
			if (!string.IsNullOrEmpty(key))
			{
				return key.Substring(key.IndexOf('_') + 1);
			}
			return string.Empty;
		}

		protected override void SetCacheSettings(PageData page, CacheSettings cacheSettings)
		{
			cacheSettings.AbsoluteExpiration = DateTime.Now.AddMinutes(10);
			cacheSettings.SlidingExpiration = TimeSpan.Zero;
		}

		protected override void SetCacheSettings(PageReference pageLink, PageReferenceCollection childrenReferences, CacheSettings cacheSettings)
		{
			cacheSettings.AbsoluteExpiration = DateTime.Now.AddMinutes(10);
			cacheSettings.SlidingExpiration = TimeSpan.Zero;
		}

		#endregion

		private Blog.Connection CurrentConnection
		{
			get
			{
				return new Blog.Connection()
											{
												Id = EntryPoint.ID,
												Username = Username,
												Password = Password,
												Url = Url,
												ProviderName = ProviderName
											};
			}
		}

		private string ProviderName
		{
			get { return GetPropertyString("BlogProvider"); }
		}

		private string Password
		{
			get { return GetPropertyString("Password"); }
		}

		private string Username
		{
			get { return GetPropertyString("Username"); }
		}

		private string Url
		{
			get { return GetPropertyString("BlogUrl"); }
		}

		private string GetPropertyString(string propertyName)
		{
			PageData page = EPiServer.DataFactory.Instance.GetPage(EntryPoint);
			if (page != null)
			{
				return (string)(page[propertyName] ?? string.Empty);
			}
			return string.Empty;
		}
	}
}